package command

import (
	"crypto/rand"
	"encoding/hex"
	"flag"
	"fmt"
	"strings"

	"github.com/mitchellh/cli"
	"github.com/tokentransfer/node/account"

	libaccount "github.com/tokentransfer/interfaces/account"
)

// GenerateCommand
type GenerateCommand struct {
	Ui cli.Ui
}

var _ cli.Command = &GenerateCommand{}

func (i *GenerateCommand) Help() string {
	helpText := `
Usage: node generate [options]
Options:
`
	return strings.TrimSpace(helpText)
}

func (i *GenerateCommand) Run(args []string) int {
	var typeString string

	cmdFlags := flag.NewFlagSet("generate", flag.PanicOnError)
	cmdFlags.Usage = func() { i.Ui.Output(i.Help()) }
	cmdFlags.StringVar(&typeString, "type", "ETH", "account type")
	if err := cmdFlags.Parse(args); err != nil {
		return 1
	}

	data := make([]byte, 32)
	_, err := rand.Reader.Read(data)
	if err != nil {
		panic(err)
	}
	seed := hex.EncodeToString(data)
	i.Ui.Output("seed: " + seed)

	as := account.GetAccountService()
	if len(typeString) > 0 {
		kt, err := libaccount.GetKeyTypeByName(typeString)
		if err != nil {
			panic(err)
		}
		as = as.WithDefaultType(kt)
	}

	tt, k, err := as.GenerateFamilySeed(seed)
	if err != nil {
		return 1
	}
	a, err := k.GetAddress()
	if err != nil {
		return 1
	}
	address := a.String()
	pub, err := k.GetPublic()
	if err != nil {
		return 1
	}
	publicString, err := pub.MarshalText()
	if err != nil {
		return 1
	}
	priv, err := k.GetPrivate()
	if err != nil {
		return 1
	}
	privateString, err := priv.MarshalText()
	if err != nil {
		return 1
	}
	i.Ui.Output("type: " + tt.String())
	i.Ui.Output("address: " + address)
	i.Ui.Output("private: " + string(privateString))
	i.Ui.Output("public: " + string(publicString))
	return 0
}

func (i *GenerateCommand) Synopsis() string {
	return "generate an account"
}

func (i *GenerateCommand) Printf(format string, v ...interface{}) {
	i.Ui.Output(fmt.Sprintf(format, v...))
}
